#include <iostream>
using namespace std;

string s;
int z[10000];

// 时间复杂度 O(n) 
// 算法步骤：
// 初始化 ：
// Z[0] = 0（约定）。
// 维护两个指针 l 和 r，表示当前已知的 最远匹配区间 [l, r]（初始时 l = r = 0）。
// 遍历每个位置 i（从 1 到 n-1） ：
// 情况1：i > r （当前字符超出已知匹配区间）：
// 从 i 开始暴力比较 s[0] 与 s[i], s[i+1], ...，直到失配。
// 设匹配长度为 len，则 Z[i] = len。
// 若 len > 0，更新 l = i, r = i + len - 1。
// 情况2：i <= r （当前字符在已知匹配区间内）：
// 利用已知区间 [l, r] 的对称性，找到 i 的对称位置 k = i - l。
// 若 Z[k] < r - i + 1：直接赋值 Z[i] = Z[k]（无需比较）。
// 若 Z[k] >= r - i + 1：从 r+1 开始继续比较，扩展匹配区间，并更新 l 和 r。

int main() {
    cin >> s;
    int l, r;
    l = r = 0;
    z[0] = s.size();
    for (int i = 1, n = s.size(); i < n; i++) {
        if (r >= i) {
            z[i] = min(z[i - l], r - i + 1);
        }
        while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i];
        if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1;
    }
    for (int i = 0; i < s.size(); i++) {
        cout << z[i] << " ";
    }
    cout << endl;
    return 0;
}